package com.diorsunion.hedge.algo;

import com.diorsunion.hedge.domain.AccountManager;
import com.diorsunion.hedge.dal.entity.stock.StockPrice;
import com.diorsunion.hedge.dal.entity.TradeLog;
import com.diorsunion.hedge.domain.MACD;
import com.diorsunion.hedge.domain.Trend;
import com.google.common.collect.Sets;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * MACD
 * 金叉买，死叉卖
 * Created by wanglaoshi on 2016/4/16.
 */
public class Oper9 extends Operation {

    public Oper9(Map<String, Integer> params) {
        super(params);
    }

    private static final Set<MACD> buy_set = Sets.newHashSet(new MACD(MACD.Type.buttom_divergence, 1), new MACD(MACD.Type.JINCHA, 3));
    private static final Set<MACD> sell_set = Sets.newHashSet(new MACD(MACD.Type.top_divergence, 1), new MACD(MACD.Type.SICHA, 3));

    private StockPrice.PriceType priceType = StockPrice.PriceType.OPEN;//用收盘价来计算
    private AccountManager account_period_begin = null;//周期记录日的账户情况,静态止损

    @Override
    public void oper(AccountManager accountManager, List<AccountManager> account_per_days) {

        if(account_per_days.size()==1){
            account_period_begin = accountManager;
        }
        if (account_per_days.size() < 3) {
            return;
        }
        AccountManager account_yes = account_per_days.get(account_per_days.size()-2);
        AccountManager account_yes_yes = account_per_days.get(account_per_days.size()-3);
        accountManager.stockPool.forEach((stock, num) -> {
            StockPrice stockPrice = stock.getStockPrice(accountManager.date);
            //用昨天的MACD作为买卖标准
            StockPrice stockPrice_yes = stock.getStockPrice(account_yes.date);
            StockPrice stockPrice_yes_yes = stock.getStockPrice(account_yes_yes.date);
            if (stockPrice_yes == null) {
                return;
            }
            //多头仓位时
            double total_current = accountManager.getTotalValue(priceType);
            double total_yes = account_yes.getTotalValue(priceType);
            double total_period = account_period_begin.getTotalValue(priceType);
            BigDecimal r0 = new BigDecimal((total_current - total_yes) * 100 / total_yes).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal r1 = new BigDecimal((total_current - total_period) * 100 / total_period).setScale(2, BigDecimal.ROUND_HALF_UP);
            int profit = params.get(PROFIT);//止盈率
            int loss = params.get(LOSS);//止损率
            int dloss = params.get(DLOSS);//止损率
            int trade_num = 0;

            if (accountManager.getStockNum(stock) == 0) {
                //空仓时
                if (stockPrice_yes.ex.macdTrend == Trend.D && stockPrice_yes.ex.macdReversePrice < stockPrice.open  && stockPrice_yes_yes.dif<stockPrice_yes.dif) {
                    //0轴以上的dif, MACD下降趋势中的转折点，此为买点
                    trade_num = (int) (accountManager.getTotalValue(priceType) / stockPrice.open / 3);
//                    System.out.println(stock.code + ":" + CalendarUtils.formatSimple(account.date) + ",趋势" + stockPrice_yes.ex.macdTrend + ",临界点价格:" + f(stockPrice_yes.ex.price) + ",开盘价:" + f(stockPrice.open) + ",开仓多单");
                }
                if (stockPrice_yes.ex.macdTrend == Trend.U && stockPrice_yes.ex.macdReversePrice > stockPrice.open  && stockPrice_yes_yes.dif>stockPrice_yes.dif) {
                    //0轴以下的dif, MACD上降趋势中的转折点，此为卖点
                    trade_num = - (int) (accountManager.getTotalValue(priceType) / stockPrice.open / 3);
//                    System.out.println(stock.code + ":" + CalendarUtils.formatSimple(account.date) + ",趋势" + stockPrice_yes.ex.macdTrend + ",临界点价格:" + f(stockPrice_yes.ex.price) + ",开盘价:" + f(stockPrice.open) + ",开仓空单");
                }
            } else {
                if (r1.intValue() >= profit) {
//                    System.out.println(
//                            "周期开始:" + CalendarUtils.formatSimple(account_period_begin.date) +
//                            ",周期结束:" + CalendarUtils.formatSimple(account.date) +
//                            ",资产净值:" + account_period_begin.getTotalValueStr(priceType) +
//                            ",当前资产净值" + account.getTotalValueStr(priceType) +
//                            ",收益率达到" + String.format("%2.2f", r1.doubleValue()) +
//                            "%,超过止盈率" + profit +
//                            "%,开始操作");
                    trade_num = -accountManager.getStockNum(stock);
                }
//                if (r0.intValue() <= dloss ) {
//                    System.out.println(
//                            "周期开始:" + CalendarUtils.formatSimple(account_yes.date) +
//                            ",周期结束:" + CalendarUtils.formatSimple(account.date) +
//                            ",资产净值:" + account_yes.getTotalValueStr(priceType) +
//                            ",当前资产净值" + account.getTotalValueStr(priceType) +
//                            ",动态损失率达到" + String.format("%2.2f", r0.doubleValue()) +
//                            "%,超过动态止损率" + dloss + "%,开始操作");
//                    trade_num = -account.getStockNum(stock);
//                }else
                if(r1.intValue()<=loss){
//                    System.out.println(
//                            "周期开始:" + CalendarUtils.formatSimple(account_yes.date) +
//                                    ",周期结束:" + CalendarUtils.formatSimple(account.date) +
//                                    ",资产净值:" + account_yes.getTotalValueStr(priceType) +
//                                    ",当前资产净值" + account.getTotalValueStr(priceType) +
//                                    ",静态损失率达到" + String.format("%2.2f", r0.doubleValue()) +
//                                    "%,超过静态止损率" + loss + "%,开始操作");
                    trade_num = -accountManager.getStockNum(stock);
                }
            }
            if(trade_num!=0){
                TradeLog tradeLog = accountManager.trade(stock, trade_num, priceType);
                account_period_begin = accountManager;
                if (tradeLog != null) {
                    tradeLogs.add(tradeLog);
                }
            }
        });
    }

    @Override
    public String getDesc() {
        return "MACD买卖法";
    }
}
